package profitcalc;
/**
 * Max profile parameter
 */
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import trading.Parameters;
import trading.Parameters.Parameter;
import trading.data.Controller;
import trading.data.IStockTickDataCollection;
import trading.formulas.MACD;
import trading.strategy.ITradingStrategy;
import trading.strategy.MACDStrategy;

public class MPPFinder {

	private ProfitCalc pc;

	public MPPFinder(ProfitCalc pc) {
		this.pc = pc;
	}

	public Parameters getParameters() {
		ITradingStrategy strategy = pc.getStrategy();
		return strategy.getParameters();
	}

	public List<List<Integer>> findMPP() {
		float maxProfit = 0;
		List<List<Integer>> result = new ArrayList<List<Integer>>(); 
		List<List<Integer>> allParams = getPossibleParams(this.getParameters(), 0);
		for (Iterator iterator = allParams.iterator(); iterator.hasNext();) {
			List<Integer> list = (List<Integer>) iterator.next();
			for( int i = 0; i<list.size(); i++)
			{
				this.getParameters().setParamValue(i, list.get(i));
			}
			
			float profit = pc.calculateProfit();
			if(Math.abs(profit - maxProfit) <= 0.0001)
			{
				result.add(list);
			}
			else if((profit -maxProfit) > 0)
			{
				maxProfit = profit;
				result.clear();
				result.add(list);
			}
		}
		
		System.out.println("Max Profit : " + maxProfit);
		
		return result;
	}

	static private List<List<Integer>> getPossibleParams(Parameters params, int index) {
		Parameter param = params.getParameter(index);
		int max = param.getParamMaxVal();
		int min = param.getParamMinVal();
		int step = param.getParamStep();

		List<List<Integer>> result = new ArrayList<List<Integer>>();

		if (index == params.getParamSize() - 1) {
			for (int i = min; i <= max; i += step) {
				List<Integer> list = new ArrayList<Integer>();
				list.add(i);
				result.add(list);
			}
		} else {
			for (int i = min; i <= max; i += step) {
				List<List<Integer>> subList = getPossibleParams(params, index + 1);
				for(int j = 0; j<subList.size(); j++)
				{
					List<Integer> list = new ArrayList<Integer>();
					list.add(i);
					list.addAll(subList.get(j));
					result.add(list);
				}
			}
		}
		
		System.out.println("size of possible params : " + result.size());
		
		return result;
	}

	static private void printParameters(List<List<Integer>> list)
	{
		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
			List<Integer> list2 = (List<Integer>) iterator.next();
			StringBuffer sb =new StringBuffer(100);
			boolean flag = false;
			for (Iterator iterator2 = list2.iterator(); iterator2.hasNext();) {
				Integer integer = (Integer) iterator2.next();
				sb.append(integer).append("; ");
			}
			System.out.println(sb.toString());
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Calendar start = Controller.createZeroCaledar();
		start.set(2006, 4 - 1, 28);
		Calendar end = Controller.createZeroCaledar();
		end.set(2009, 8 - 1, 24);
		
		IStockTickDataCollection dataCollection = Controller.getTickData();
		MACDStrategy strategy = MACDStrategy.getMACDStrategy();
		Parameters params = strategy.getParameters();
		Parameter longP = params.getParameter(MACD.LONG_IDX);
		longP.setParamMaxVal(250);
		longP.setParamMinVal(200);
		longP.setParamStep(2);
		
		Parameter shortP = params.getParameter(MACD.SHORT_IDX);
		shortP.setParamMaxVal(70);
		shortP.setParamMinVal(50);
		shortP.setParamStep(2);
		
		Parameter mP = params.getParameter(MACD.M_IDX);
		mP.setParamMaxVal(3);
		mP.setParamMinVal(1);
		mP.setParamStep(1);
		
//		printParameters(getPossibleParams(params, 0));
		
		ProfitCalc pc = new ProfitCalc(dataCollection, strategy, start, end);
		long time1 = System.currentTimeMillis();
		List<List<Integer>> list = new MPPFinder(pc).findMPP();
		
		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
			List<Integer> list2 = (List<Integer>) iterator.next();
			StringBuffer sb =new StringBuffer(100);
			for (Iterator iterator2 = list2.iterator(); iterator2.hasNext();) {
				Integer integer = (Integer) iterator2.next();
				sb.append(integer).append("; ");
			}
			System.out.println(sb.toString());
		}
		System.out.println(System.currentTimeMillis()-time1);
	}

}
